package cn.brilliantfuture.commentry.delivery.impl;

import java.text.MessageFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.jws.WebService;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import net.sf.json.JSONObject;

import org.apache.log4j.Logger;
import org.jboss.wsf.spi.annotation.WebContext;

import com.acsm.commons.sms.AlidayuSMS;
import com.acsm.commons.sms.SaveSmsInfo;

import cn.brilliantfuture.commentry.constants.OrderConstant;
import cn.brilliantfuture.commentry.delivery.StorageDeliveryMessageRemote;
import cn.brilliantfuture.commentry.delivery.StorageDeliveryMessageWebService;
import cn.brilliantfuture.commentry.entity.CardInfo;
import cn.brilliantfuture.commentry.entity.DeliveryPlan;
import cn.brilliantfuture.commentry.entity.DeliveryRecord;
import cn.brilliantfuture.commentry.entity.EmailInfo;
import cn.brilliantfuture.commentry.entity.ExpressPerson;
import cn.brilliantfuture.commentry.entity.Lockers;
import cn.brilliantfuture.commentry.entity.OrderInformation;
import cn.brilliantfuture.commentry.entity.PickRecords;
import cn.brilliantfuture.commentry.entity.ProductBatch;
import cn.brilliantfuture.commentry.entity.Purchaser;
import cn.brilliantfuture.commentry.entity.RefundPickRecords;
import cn.brilliantfuture.commentry.entity.SmsInfo;
import cn.brilliantfuture.commentry.entity.StorageGrid;
import cn.brilliantfuture.commentry.entity.StorageGridPurchaserNews;
import cn.brilliantfuture.commentry.entity.StorageServiceKey;
import cn.brilliantfuture.commentry.entity.UserGroup;
import cn.brilliantfuture.commentry.inform.InformMessageLocal;
import cn.brilliantfuture.commentry.order.WorkflowMessageLocal;
import cn.brilliantfuture.commentry.util.CommEntryUtil;
import cn.brilliantfuture.commentry.util.DateTimeHelper;
import cn.brilliantfuture.commentry.util.EMAILScheduler;
import cn.brilliantfuture.commentry.util.RESTUtil;
import cn.brilliantfuture.commentry.util.SMSScheduler;

/**
 * 
 * Title: Communication Entry
 * 
 * Author:  LiTian  
 *
 * Date: 2012-8-23
 * 
 * Description:
 * 
 */
@Stateless
@WebService(endpointInterface = "cn.brilliantfuture.commentry.delivery.StorageDeliveryMessageWebService")
@WebContext(contextRoot = "/commentry", urlPattern = "/StorageDeliveryMessageWebService")
public class StorageDeliveryMessageImpl implements StorageDeliveryMessageRemote, StorageDeliveryMessageWebService {
	
	private static Logger logger = Logger.getLogger(StorageDeliveryMessageImpl.class);
	
	@PersistenceContext
	EntityManager entityManager;
	
	@EJB InformMessageLocal informMessage;
	
	@EJB WorkflowMessageLocal workflowMessageLocal;

	/*@SuppressWarnings("unchecked")
	public String safeStorageDelivery(String deviceSn, int gridNo, String storageRfid, String timestamp) {
		
		logger.info("deviceSn -> " + deviceSn + " gridNo -> " + gridNo + " storageRfid -> " + storageRfid + " timestamp -> " + timestamp);
		
		JSONObject result = new JSONObject();
		
		Date deliveryTime = DateTimeHelper.strToDateTime(timestamp, DateTimeHelper.DEFAULT_DATE_TIME_NOT_SPACE_FORMAT);
		
		List<StorageServiceInfo> storageServiceInfoList = entityManager.createQuery("select ssi from StorageServiceInfo ssi where ssi.storageRfid = '" + storageRfid + "'").getResultList();
		List<StorageGrid> storageGridList = entityManager.createQuery("select sg from StorageGrid sg inner join sg.lockers l where sg.deleted = 0 and l.deleted = 0 and sg.gridNum = " + gridNo + " and l.device.deviceSn = '" + deviceSn + "'").getResultList();
		if (null == storageServiceInfoList || storageServiceInfoList.size() == 0){
			result.accumulate("userId", "000000000");
			result.accumulate("passwd", "000000");
			return result.toString();
		}
		
		if (null == storageGridList || storageGridList.size() == 0){
			result.accumulate("userId", "000000000");
			result.accumulate("passwd", "000000");
			return result.toString();
		}
		
		StorageServiceInfo storageServiceInfo = storageServiceInfoList.get(0);
		StorageGrid storageGrid = storageGridList.get(0);
		UserGroup group = entityManager.find(UserGroup.class, storageServiceInfo.getGroupId());
		
		if (storageServiceInfo.isEnable()){

			OrderInformation orderInformation = new OrderInformation();
			orderInformation.setNumber(group.getGroupId() + String.valueOf(System.currentTimeMillis()));
			orderInformation.setPurchaser(storageServiceInfo.getPurchaser());
			orderInformation.setReceiveName(storageServiceInfo.getPurchaser().getRealname());
			orderInformation.setReceivePhone(storageServiceInfo.getPurchaser().getPhone());
			orderInformation.setRecevieEmail(storageServiceInfo.getPurchaser().getEmail());
			orderInformation.setLockers(storageGrid.getLockers());
			orderInformation.setGroup(group);
			orderInformation.setStoreMode(OrderConstant.GENERAL_STORE_TYPE);
			orderInformation.setPaymentMode(OrderConstant.VIGGIEHOME_PAYMENT_MODE);
			orderInformation.setTotalAmount(0.0D);
			orderInformation.setOrderSource(OrderConstant.ORDER_SOURCE_VIGGIEHOME);
			orderInformation.setOrderType(OrderConstant.STORAGE_ORDER_TYPE);
			orderInformation.setTransactions(OrderConstant.DONE_DELIVERY);
			orderInformation.setDataModels(null);
			orderInformation.setEffective(true);
			orderInformation.setManual(false);
			orderInformation.setDeleted(false);
			orderInformation.setInsertTime(new Date());
			
			entityManager.persist(orderInformation);
			
			ExpenseRecord expenseRecord = new ExpenseRecord();
			expenseRecord.setPurchaserId(storageServiceInfo.getPurchaser().getPurchaserId());
			expenseRecord.setGroupId(group.getGroupId());
			expenseRecord.setType(1);
			expenseRecord.setExpenseCode(group.getGroupId() + String.valueOf(System.currentTimeMillis()));
			expenseRecord.setOrderCode(orderInformation.getNumber());
			expenseRecord.setAmount(0.0D);
			expenseRecord.setExpenseBeforeBalance(storageServiceInfo.getPurchaser().getAmount());
			expenseRecord.setExpenseAfterBalance(storageServiceInfo.getPurchaser().getAmount());
			expenseRecord.setExpenseTime(new Date());
			expenseRecord.setExpenseNote("绿色家递收储业务支付，支付方式为绿色家递支付");
			
			entityManager.persist(expenseRecord);
			
			StorageGridPurchaserNews sgpn = new StorageGridPurchaserNews();
			sgpn.setStorageGrid(storageGrid);
			sgpn.setCardNumber(storageServiceInfo.getPurchaser().getCardInfo().getCardNumber());
			sgpn.setDelivery(1);
			sgpn.setClosing(0);
			sgpn.setArrivalTime(deliveryTime);
			sgpn.setPick(0);
			sgpn.setRfidSn(storageServiceInfo.getStorageRfid());
			sgpn.setPurchaser(storageServiceInfo.getPurchaser());
			sgpn.setLockersId(storageGrid.getLockers().getLockersId());
			sgpn.setLocationId(storageGrid.getLockers().getLocation().getLocationId());
			sgpn.setOrderInformationNumber(orderInformation.getNumber());
			sgpn.setGroupId(group.getGroupId());
			sgpn.setDeviceSn(deviceSn);
			sgpn.setRefund(0);
			
			entityManager.persist(sgpn);
			
			storageServiceInfo.setEnable(false);
			storageServiceInfo.setDeliveryTime(deliveryTime);
			storageServiceInfo.setOrderInformationId(orderInformation.getOrderInformationId());
			
			entityManager.merge(storageServiceInfo);
			
			entityManager.flush();
			
			String phone = storageServiceInfo.getPurchaser().getPhone();
			String email = storageServiceInfo.getPurchaser().getEmail();
			
			Map<String, Object> informMap = informMessage.queryInformMessage(storageServiceInfo.getPurchaser().getLanguage(), 2, 3);
			
			Object[] objs = {storageGrid.getLockers().getLocation().getVilliage().getName() + storageGrid.getLockers().getLocation().getName() + storageGrid.getLockers().getLockersName(), storageServiceInfo.getStoragePasswd(), group.getHotline()};
			
			if (null != phone && !"".equals(phone) && informMap.containsKey(InformMessageLocal.SMS_INFORM)){
				String message = ((SmsInfo)informMap.get(InformMessageLocal.SMS_INFORM)).getSmsContent();
				
				message = MessageFormat.format(message, objs);
				
				logger.info("SMS message -> " + message);
				
				new SMSScheduler(phone, message, SMSScheduler.MMS_CAT_CHANNEL, group.getName(), true).start();
				
			} else if (null != email && !"".equals(email) && informMap.containsKey(InformMessageLocal.EMAIL_INFORM)){
				EmailInfo emailInfo = (EmailInfo) informMap.get(InformMessageLocal.EMAIL_INFORM);
				
				String message = emailInfo.getContent();
				
				message = MessageFormat.format(message, objs);
				
				logger.info("E-MAIL message -> " + message);
				
				new EMAILScheduler(email, emailInfo.getTitle(), message).start();
				
			}

			result.accumulate("userId", storageServiceInfo.getPurchaser().getCardInfo().getCardNumber());
			result.accumulate("passwd", storageServiceInfo.getStoragePasswd());
		} else {
			result.accumulate("userId", storageServiceInfo.getPurchaser().getCardInfo().getCardNumber());
			result.accumulate("passwd", storageServiceInfo.getStoragePasswd());

			
		}
		
		JSONObject param = new JSONObject();
		param.accumulate("lockers_id", storageGrid.getLockers().getLockersId());
		param.accumulate("store_code", storageRfid);
		param.accumulate("service_type", 1);
		param.accumulate("deliver_time", timestamp);
		param.accumulate("phone", "");
		
		logger.info(RESTUtil.getRESTInvoke(RESTUtil.DELIVER_INFO_CALLBACK_METHOD, param.toString()));
		
		return result.toString();
	}*/
	
	@SuppressWarnings("unchecked")
	public String safeStorageDelivery(String deviceSn, int gridNo, String storageRfid, String timestamp) {
		
		logger.info("deviceSn -> " + deviceSn + " gridNo -> " + gridNo + " storageRfid -> " + storageRfid + " timestamp -> " + timestamp);
		
		JSONObject result = new JSONObject();
		
		StorageGridPurchaserNews sgpn = null;
		Date deliveryTime = DateTimeHelper.strToDateTime(timestamp, DateTimeHelper.DEFAULT_DATE_TIME_NOT_SPACE_FORMAT);

		//查找送货信息是否已经存在
		//Query queryExist = entityManager.createQuery("select sgpn from StorageGridPurchaserNews sgpn where sgpn.closing = 0 and sgpn.storageGrid.gridNum = :gridNum and sgpn.deviceSn = :deviceSn and sgpn.rfidSn = :rfidSn");
		Query queryExist = entityManager.createQuery("select sgpn from StorageGridPurchaserNews sgpn where sgpn.closing = 0 and sgpn.deviceSn = :deviceSn and sgpn.rfidSn = :rfidSn");
		//List<StorageGridPurchaserNews> deliveryRecordExist = queryExist.setParameter("gridNum", gridNo).setParameter("deviceSn", deviceSn).setParameter("rfidSn", storageRfid).getResultList();
		List<StorageGridPurchaserNews> deliveryRecordExist = queryExist.setParameter("deviceSn", deviceSn).setParameter("rfidSn", storageRfid).getResultList();
		
		//如果存在，直接返回会员ID及取货密码
		if (null != deliveryRecordExist && deliveryRecordExist.size() > 0){
			List<ProductBatch> productBatchs = entityManager.createQuery("select pb from ProductBatch pb where pb.rfidSn = '" + storageRfid + "'").getResultList();
			logger.info("Receive Repeat delivery info ...");
			
			result.accumulate("userId", deliveryRecordExist.get(0).getCardNumber());
			result.accumulate("passwd", productBatchs.get(0).getPasswd());
			return result.toString();
		}

		//确定配送仓状态是否错误
		Query query = entityManager.createQuery("select sgpn from StorageGridPurchaserNews sgpn where sgpn.closing = 0 and sgpn.storageGrid.gridNum = :gridNum and sgpn.deviceSn = :deviceSn");
		List<StorageGridPurchaserNews> oldsgpns = query.setParameter("gridNum", gridNo).setParameter("deviceSn", deviceSn).getResultList();

		// 修改历史数据并察看当前货号是否已经存在
		for (StorageGridPurchaserNews oldsgpn : oldsgpns) {
			logger.info("Current storage grid used! orderInfoNum -> " + oldsgpn.getOrderInformationNumber());

			if (oldsgpn.getRfidSn().equals(storageRfid))
				sgpn = oldsgpn;
			else {
				oldsgpn.setTakeawayTime(new Date());
				oldsgpn.setClosing(1);
				oldsgpn.setPick(1);
				entityManager.merge(oldsgpn);

				// 插入取货记录
				if (oldsgpn.getRefund() == 0) {
					PickRecords pickRecords = new PickRecords();
					pickRecords.setCardNumber(oldsgpn.getCardNumber());
					pickRecords.setFlag(true);
					pickRecords.setInsertTime(DateTimeHelper.dateTimeToStr(new Date(), DateTimeHelper.DEFAULT_DATE_TIME_FORMAT));
					pickRecords.setOrderInformationNumber(oldsgpn.getOrderInformationNumber());
					pickRecords.setRfidSn(oldsgpn.getRfidSn());
					pickRecords.setGridNum(gridNo);
					entityManager.persist(pickRecords);

					// 修改配送单状态
					entityManager.createNativeQuery("update order_information set transactions = 5 where number = :orderNumber").setParameter("orderNumber", oldsgpn.getOrderInformationNumber()).executeUpdate();
				} else if (oldsgpn.getRefund() == 1) {
					RefundPickRecords refundPickRecords = new RefundPickRecords();
					refundPickRecords.setCardNumber(oldsgpn.getCardNumber());
					refundPickRecords.setFlag(true);
					refundPickRecords.setPickTime(new Date());
					refundPickRecords.setOrderInfoNumber(oldsgpn.getOrderInformationNumber());
					refundPickRecords.setRfidSn(oldsgpn.getRfidSn());
					refundPickRecords.setGridNumber(gridNo);
					entityManager.persist(refundPickRecords);

					// 修改配送单状态
					entityManager.createNativeQuery("update refund_order_info set transactions = 3 where order_info_number = :orderNumber").setParameter("orderNumber", oldsgpn.getOrderInformationNumber()).executeUpdate();
				}

				entityManager.flush();
			}
		}
		
		List<OrderInformation> orderInfos = entityManager.createQuery("select oi from OrderInformation oi inner join oi.productBatchs pb where oi.deleted = 0 and pb.deleted = 0 and pb.rfidSn = :rfidSn").setParameter("rfidSn", storageRfid).getResultList();
		StorageGrid storageGrid = null;
		if (orderInfos.size() != 1) {
			result.accumulate("userId", "000000000");
			result.accumulate("passwd", "000000");
			return result.toString();
		}
		
		OrderInformation orderInfo = orderInfos.get(0);
		
		Set<ProductBatch> productBatchs = orderInfo.getProductBatchs();

		for (Iterator<ProductBatch> it = productBatchs.iterator(); it.hasNext();) {
			ProductBatch productBatch = it.next();
			if (productBatch.isDeleted())
				it.remove();
		}
		
		String passwd = "";
		
		DeliveryPlan deliveryPlan = null;

		// 获取RFID
		for (ProductBatch productBatch : productBatchs){
			if (productBatch.getRfidSn().equals(storageRfid)) {
				passwd = productBatch.getPasswd();
				deliveryPlan = productBatch.getDeliveryPlan();
				break;
			}
		}

		//更新配送地址
		if (null == orderInfo.getLockers().getDevice()) {
			List<Lockers> lockersList = entityManager.createQuery("select l from Lockers l where l.device is not null and l.deleted = 0 and l.device.deviceSn = :deviceSn").setParameter("deviceSn", deviceSn).getResultList();
			if (null != lockersList)
				if (lockersList.size() == 1) {
					orderInfo.setLockers(lockersList.get(0));
					entityManager.merge(orderInfo);
				}
		} else if (!orderInfo.getLockers().getDevice().getDeviceSn().equals(deviceSn)) {
			List<Lockers> lockersList = entityManager.createQuery("select l from Lockers l where l.device is not null and l.deleted = 0 and l.device.deviceSn = :deviceSn").setParameter("deviceSn", deviceSn).getResultList();
			if (null != lockersList)
				if (lockersList.size() == 1) {
					orderInfo.setLockers(lockersList.get(0));
					entityManager.merge(orderInfo);
				}

		}
		
		for (StorageGrid sg : orderInfo.getLockers().getStorageGrids()){
			if (sg.getGridNum() == gridNo) {
				storageGrid = sg;
				break;
			}
		}
		
		if (deliveryPlan.getStorageGrid().getGridNum().intValue() != storageGrid.getGridNum().intValue()){
			deliveryPlan.setStorageGrid(storageGrid);
			entityManager.merge(deliveryPlan);
		}
		
		if (deliveryPlan.getPlanType() == 2) {
			deliveryPlan.setPlanType(1);
			deliveryPlan.setUnreserveTime(null);
			entityManager.merge(deliveryPlan);
		}
		
		/*List<DeliveryPlan> deliveryPlans = entityManager.createQuery("select dp from DeliveryPlan dp where dp.planType = 1 and dp.orderInformation.orderInformationId = " + orderInfo.getOrderInformationId() + " and dp.storageGrid.storageGridId = " + storageGrid.getStorageGridId()).getResultList();
		
		if (deliveryPlans.size() == 0){
			result.accumulate("userId", "000000000");
			result.accumulate("passwd", "000000");
			return result.toString();
		}*/

		if (null == sgpn) {
			// 组织配送信息
			sgpn = new StorageGridPurchaserNews();
			sgpn.setStorageGrid(storageGrid);
			sgpn.setCardNumber(orderInfo.getPurchaser().getCardInfo().getCardNumber());
			sgpn.setDelivery(1);
			sgpn.setDeliveryPlan(deliveryPlan);
			sgpn.setClosing(0);
			sgpn.setArrivalTime(deliveryTime);
			sgpn.setPick(0);
			sgpn.setRfidSn(storageRfid);
			sgpn.setPurchaser(orderInfo.getPurchaser());
			sgpn.setLockersId(orderInfo.getLockers().getLockersId());
			sgpn.setLocationId(orderInfo.getLockers().getLocation().getLocationId());
			sgpn.setOrderInformationNumber(orderInfo.getNumber());
			sgpn.setGroupId(orderInfo.getGroup().getGroupId());
			sgpn.setDeviceSn(deviceSn);
			sgpn.setRefund(0);
			entityManager.persist(sgpn);

			// 组织配送记录信息
			DeliveryRecord deliveryRecord = new DeliveryRecord();
			deliveryRecord.setCardNumber(orderInfo.getPurchaser().getCardInfo().getCardNumber());
			deliveryRecord.setRfidSn(storageRfid);
			deliveryRecord.setGridNum(gridNo);
			deliveryRecord.setInsertTime(DateTimeHelper.dateTimeToStr(deliveryTime, DateTimeHelper.DEFAULT_DATE_TIME_FORMAT));
			deliveryRecord.setLocation(orderInfo.getLockers().getLocation().getVilliage().getName() + orderInfo.getLockers().getLocation().getName() + orderInfo.getLockers().getLockersName());
			deliveryRecord.setPurchaserName(orderInfo.getPurchaser().getName());
			entityManager.persist(deliveryRecord);
		}
		
		orderInfo.setTransactions(6);
		orderInfo.setEffective(true);
		entityManager.merge(orderInfo);
		
		workflowMessageLocal.createWorkflowInfo(orderInfo, 3, "货品已送至" + orderInfo.getLockers().getLocation().getDescription() + orderInfo.getLockers().getLockersName(), DateTimeHelper.strToDateTime(DateTimeHelper.dateTimeToStr(new Date(), DateTimeHelper.DEFAULT_YEAR_FORMAT) + CommEntryUtil.getFormatStr(timestamp, 10), DateTimeHelper.DEFAULT_DATE_TIME_NOT_SPACE_FORMAT), "系统", 3);

		String phone = orderInfo.getPurchaser().getPhone();
		String email = orderInfo.getPurchaser().getEmail();
		
		Map<String, Object> informMap = informMessage.queryInformMessage(orderInfo.getPurchaser().getLanguage(), 2, 3);
		
		Object[] objs = {storageGrid.getLockers().getLocation().getVilliage().getName() + storageGrid.getLockers().getLocation().getName() + storageGrid.getLockers().getLockersName(), passwd, orderInfo.getGroup().getHotline()};
		
		if (null != phone && !"".equals(phone) && informMap.containsKey(InformMessageLocal.SMS_INFORM)){
			String message = ((SmsInfo)informMap.get(InformMessageLocal.SMS_INFORM)).getSmsContent();
			
			message = MessageFormat.format(message, objs);
			
			logger.info("SMS message -> " + message);
			
			//new SMSScheduler(phone, message, objs, "123", orderInfo.getGroup().getSmsChannel(), orderInfo.getGroup().getName(), true).start();
			
			String papams="{\"address\":\""+objs[0]+"\",\"passwd\":\""+objs[1]+"\"}";
			new AlidayuSMS(phone,"SMS_5450197","到货通知",papams,message,new SaveSmsInfo()).start();
			
			workflowMessageLocal.createWorkflowInfo(orderInfo.getNumber(), 1, "发送送货信息...", DateTimeHelper.strToDateTime(DateTimeHelper.dateTimeToStr(new Date(), DateTimeHelper.DEFAULT_YEAR_FORMAT) + CommEntryUtil.getFormatStr(timestamp, 10), DateTimeHelper.DEFAULT_DATE_TIME_NOT_SPACE_FORMAT), "系统", 4);
		} else if (null != email && !"".equals(email) && informMap.containsKey(InformMessageLocal.EMAIL_INFORM)){
			EmailInfo emailInfo = (EmailInfo) informMap.get(InformMessageLocal.EMAIL_INFORM);
			
			String message = emailInfo.getContent();
			
			message = MessageFormat.format(message, objs);
			
			logger.info("E-MAIL message -> " + message);
			
			new EMAILScheduler(email, emailInfo.getTitle(), message).start();
			
			workflowMessageLocal.createWorkflowInfo(orderInfo.getNumber(), 1, "发送送货信息...", DateTimeHelper.strToDateTime(DateTimeHelper.dateTimeToStr(new Date(), DateTimeHelper.DEFAULT_YEAR_FORMAT) + CommEntryUtil.getFormatStr(timestamp, 10), DateTimeHelper.DEFAULT_DATE_TIME_NOT_SPACE_FORMAT), "系统", 4);
		}

		result.accumulate("userId", orderInfo.getPurchaser().getCardInfo().getCardNumber());
		result.accumulate("passwd", passwd);
		
		JSONObject param = new JSONObject();
		param.accumulate("lockers_id", storageGrid.getLockers().getLockersId());
		param.accumulate("store_code", storageRfid);
		param.accumulate("service_type", 1);
		param.accumulate("deliver_time", deliveryTime.getTime());
		
		logger.info(RESTUtil.getRESTInvoke(RESTUtil.DELIVER_INFO_CALLBACK_METHOD, param.toString()));
		
		entityManager.flush();
		
		return result.toString();
	}

	@SuppressWarnings("unchecked")
	public String easyStorageDelivery(String deviceSn, int gridNo, String storageRfid, String phone, String timestamp) {
		logger.info("deviceSn -> " + deviceSn + " gridNo -> " + gridNo + " storageRfid -> " + storageRfid + " phone -> " + phone + " timestamp -> " + timestamp);
		
		JSONObject result = new JSONObject();

		Date deliveryTime = DateTimeHelper.strToDateTime(timestamp, DateTimeHelper.DEFAULT_DATE_TIME_NOT_SPACE_FORMAT);
		
		List<StorageServiceKey> storageServiceKeyList = entityManager.createQuery("select ssk from StorageServiceKey ssk inner join ssk.purchaser p inner join ssk.lockers l where p.phone = '" + phone + "' and l.device.deviceSn = '" + deviceSn + "' order by ssk.storageServiceKeyId desc").setMaxResults(1).getResultList();
		
		if (null == storageServiceKeyList || storageServiceKeyList.size() == 0){
			result.accumulate("userId", "000000000");
			result.accumulate("passwd", "000000");
			return result.toString();
		}
		
		List<StorageGrid> storageGridList = entityManager.createQuery("select sg from StorageGrid sg inner join sg.lockers l where sg.deleted = 0 and l.deleted = 0 and sg.gridNum = " + gridNo + " and l.device.deviceSn = '" + deviceSn + "'").getResultList();
		
		if (null == storageGridList || storageGridList.size() == 0){
			result.accumulate("userId", "000000000");
			result.accumulate("passwd", "000000");
			return result.toString();
		}
		
		StorageServiceKey storageServiceKey = storageServiceKeyList.get(0);
		StorageGrid storageGrid = storageGridList.get(0);
		UserGroup group = entityManager.find(UserGroup.class, storageServiceKey.getGroupId());
		
		OrderInformation orderInformation = new OrderInformation();
		orderInformation.setNumber(group.getGroupId() + String.valueOf(System.currentTimeMillis()));
		orderInformation.setPurchaser(storageServiceKey.getPurchaser());
		orderInformation.setReceiveName(storageServiceKey.getPurchaser().getRealname());
		orderInformation.setReceivePhone(storageServiceKey.getPurchaser().getPhone());
		orderInformation.setRecevieEmail(storageServiceKey.getPurchaser().getEmail());
		orderInformation.setLockers(storageServiceKey.getLockers());
		orderInformation.setGroup(group);
		orderInformation.setStoreMode(OrderConstant.GENERAL_STORE_TYPE);
		orderInformation.setPaymentMode(OrderConstant.VIGGIEHOME_PAYMENT_MODE);
		orderInformation.setTotalAmount(0.0D);
		orderInformation.setOrderSource(OrderConstant.ORDER_SOURCE_VIGGIEHOME);
		orderInformation.setOrderType(OrderConstant.STORAGE_ORDER_TYPE);
		orderInformation.setTransactions(OrderConstant.DONE_DELIVERY);
		orderInformation.setEasyStorageKey(storageServiceKey.getStorageServiceKeyId());
		orderInformation.setDataModels(null);
		orderInformation.setEffective(true);
		orderInformation.setManual(false);
		orderInformation.setDeleted(false);
		orderInformation.setInsertTime(new Date());
		
		entityManager.persist(orderInformation);
		
		String passwd = CommEntryUtil.confuse(calculatePasswd(CommEntryUtil.bernstein(storageRfid)));
		
		ProductBatch productBatch = new ProductBatch();
		productBatch.setStoreMode(OrderConstant.GENERAL_STORE_TYPE);
		productBatch.setRfidSn(storageRfid);
		productBatch.setPasswd(passwd);
		productBatch.setOrderInformation(orderInformation);
		productBatch.setInsertTime(new Date());
		productBatch.setDeleted(false);
		
		entityManager.persist(productBatch);
		
		StorageGridPurchaserNews sgpn = new StorageGridPurchaserNews();
		sgpn.setStorageGrid(storageGrid);
		sgpn.setCardNumber(storageServiceKey.getPurchaser().getCardInfo().getCardNumber());
		sgpn.setDelivery(1);
		sgpn.setClosing(0);
		sgpn.setArrivalTime(deliveryTime);
		sgpn.setPick(0);
		sgpn.setRfidSn(storageRfid);
		sgpn.setPurchaser(storageServiceKey.getPurchaser());
		sgpn.setLockersId(storageGrid.getLockers().getLockersId());
		sgpn.setLocationId(storageGrid.getLockers().getLocation().getLocationId());
		sgpn.setOrderInformationNumber(orderInformation.getNumber());
		sgpn.setGroupId(group.getGroupId());
		sgpn.setDeviceSn(deviceSn);
		sgpn.setRefund(0);
		
		entityManager.persist(sgpn);
		
		entityManager.flush();

		String email = storageServiceKey.getPurchaser().getEmail();
		
		Map<String, Object> informMap = informMessage.queryInformMessage(storageServiceKey.getPurchaser().getLanguage(), 2, 3);
		
		Object[] objs = {storageGrid.getLockers().getLocation().getVilliage().getName() + storageGrid.getLockers().getLocation().getName() + storageGrid.getLockers().getLockersName(), passwd, group.getHotline()};
		
		if (null != phone && !"".equals(phone) && informMap.containsKey(InformMessageLocal.SMS_INFORM)){
			String message = ((SmsInfo)informMap.get(InformMessageLocal.SMS_INFORM)).getSmsContent();
			
			message = MessageFormat.format(message, objs);
			
			logger.info("SMS message -> " + message);
			
			//new SMSScheduler(phone, message, objs, "123", group.getSmsChannel(), group.getName(), true).start();
			
			String papams="{\"address\":\""+objs[0]+"\",\"passwd\":\""+objs[1]+"\"}";
			new AlidayuSMS(phone,"SMS_5450197","到货通知",papams,message,new SaveSmsInfo()).start();
			
		} else if (null != email && !"".equals(email) && informMap.containsKey(InformMessageLocal.EMAIL_INFORM)){
			EmailInfo emailInfo = (EmailInfo) informMap.get(InformMessageLocal.EMAIL_INFORM);
			
			String message = emailInfo.getContent();
			
			message = MessageFormat.format(message, objs);
			
			logger.info("E-MAIL message -> " + message);
			
			new EMAILScheduler(email, emailInfo.getTitle(), message).start();
			
		}
		
		result.accumulate("userId", storageServiceKey.getPurchaser().getCardInfo().getCardNumber());
		result.accumulate("passwd", passwd);
		
		JSONObject param = new JSONObject();
		param.accumulate("lockers_id", storageServiceKey.getLockers().getLockersId());
		param.accumulate("store_code", storageRfid);
		param.accumulate("service_type", 2);
		param.accumulate("deliver_time", timestamp);
		param.accumulate("phone", phone);
		
		logger.info(RESTUtil.getRESTInvoke(RESTUtil.DELIVER_INFO_CALLBACK_METHOD, param.toString()));
		
		return result.toString();
	}
	
	private static String calculatePasswd(String rfid_sn) {
		StringBuffer sb = new StringBuffer();
		String done = rfid_sn.substring(7, 19);
		sb.append(done.charAt(3));
		sb.append(done.charAt(7));
		sb.append(done.charAt(4));
		sb.append(done.charAt(10));
		sb.append(done.charAt(2));
		sb.append(done.charAt(5));
		return sb.toString();
	}

	@SuppressWarnings("unchecked")
	public String expressDelivery(String deviceSn, int gridNo, String storageRfid, String phone, String timestamp, String deliverMan) {
		logger.info("deviceSn -> " + deviceSn + " gridNo -> " + gridNo + " storageRfid -> " + storageRfid + " phone -> " + phone + " timestamp -> " + timestamp + " deliverMan -> " + deliverMan);
		
		JSONObject result = new JSONObject();
		
		List<ProductBatch> productBatchs = entityManager.createQuery("select pb from ProductBatch pb where pb.rfidSn = '" + storageRfid + "'").getResultList();
		
		if (productBatchs.size() > 0) {
			logger.info("RFID SN is exist!");
			ProductBatch productBatch = productBatchs.get(0);
			result.accumulate("userId", productBatch.getOrderInformation().getPurchaser().getCardInfo().getCardNumber());
			result.accumulate("passwd", productBatch.getPasswd());
			return result.toString();
		}
		
		Date deliveryTime = DateTimeHelper.strToDateTime(timestamp, DateTimeHelper.DEFAULT_DATE_TIME_NOT_SPACE_FORMAT);
		
		List<ExpressPerson> expressPersons = entityManager.createQuery("select ep from ExpressPerson ep where ep.deleted = false and ep.expressCode = '" + deliverMan + "'").getResultList();
		
		List<Lockers> lockers = entityManager.createQuery("select l from Lockers l where l.deleted = false and l.device.deviceSn = '" + deviceSn + "'").getResultList();
		
		if (expressPersons.size() != 1 || lockers.size() != 1) {
			result.accumulate("userId", "000000000");
			result.accumulate("passwd", "000000");
			return result.toString();
		}
		
		List<Purchaser> purchasers = entityManager.createQuery("select p from Purchaser p where p.deleted = false and p.phone = '" + phone + "'").getResultList();
		
		Purchaser purchaser = null;
		
		if (purchasers.size() > 0) {
			purchaser = purchasers.get(0);
		} else {
			List<CardInfo> cardInfos = entityManager.createQuery("select ci from CardInfo ci where ci.deleted = 0 and ci.purchaser.purchaserId is null").setMaxResults(1).getResultList();
			CardInfo cardInfo = null;
			if (null != cardInfos && cardInfos.size() > 0) {
				cardInfo = cardInfos.get(0);
			} else {
				Object obj = entityManager.createNativeQuery("select card_number from card_info where deleted = 0 order by card_number desc").setMaxResults(1).getSingleResult();

				long number = Long.parseLong(obj.toString()) + 1;
				cardInfo = new CardInfo();
				cardInfo.setCardNumber(CommEntryUtil.getFormatStr(number + "", 9));
				cardInfo.setActive(1);
				cardInfo.setType(1);
				cardInfo.setDeleted(false);
				
				entityManager.persist(cardInfo);
			}
			
			String password = CommEntryUtil.randomPasswd();

			purchaser = new Purchaser();
			purchaser.setName(cardInfo.getCardNumber());
			purchaser.setPassword(CommEntryUtil.encodePassword(password, "SHA"));
			purchaser.setPhone(phone);
			purchaser.setInsertTime(new Date());
			purchaser.setAmount(0.0D);
			purchaser.setLanguage(1);
			purchaser.setTemporary(true);
			purchaser.setDeleted(false);
			
			entityManager.persist(purchaser);
			
			cardInfo.setPurchaser(purchaser);
			entityManager.merge(cardInfo);
			
			purchaser.setCardInfo(cardInfo);
		}
		
		UserGroup group = expressPersons.get(0).getExpressInfo().getGroup();
		
		OrderInformation orderInformation = new OrderInformation();
		orderInformation.setNumber(group.getGroupId() + String.valueOf(System.currentTimeMillis()));
		orderInformation.setPurchaser(purchaser);
		orderInformation.setReceiveName(purchaser.getRealname());
		orderInformation.setReceivePhone(purchaser.getPhone());
		orderInformation.setRecevieEmail(purchaser.getEmail());
		orderInformation.setLockers(lockers.get(0));
		orderInformation.setGroup(group);
		orderInformation.setStoreMode(OrderConstant.GENERAL_STORE_TYPE);
		orderInformation.setPaymentMode(OrderConstant.VIGGIEHOME_PAYMENT_MODE);
		orderInformation.setTotalAmount(0.0D);
		orderInformation.setOrderSource(OrderConstant.ORDER_SOURCE_VIGGIEHOME);
		orderInformation.setOrderType(OrderConstant.EXPRESS_ORDER_TYPE);
		orderInformation.setTransactions(OrderConstant.DONE_DELIVERY);
		orderInformation.setDataModels(null);
		orderInformation.setEffective(true);
		orderInformation.setManual(false);
		orderInformation.setDeleted(false);
		orderInformation.setInsertTime(new Date());
		orderInformation.setExpressInfo(expressPersons.get(0).getExpressInfo());
		orderInformation.setExpressPerson(expressPersons.get(0));
		
		entityManager.persist(orderInformation);
		
		String passwd = CommEntryUtil.confuse(calculatePasswd(CommEntryUtil.bernstein(storageRfid)));
		
		passwd = getPasswd(passwd);
		
		ProductBatch productBatch = new ProductBatch();
		productBatch.setStoreMode(OrderConstant.GENERAL_STORE_TYPE);
		productBatch.setRfidSn(storageRfid);
		productBatch.setPasswd(passwd);
		productBatch.setOrderInformation(orderInformation);
		productBatch.setInsertTime(new Date());
		productBatch.setDeleted(false);
		
		entityManager.persist(productBatch);
		
		StorageGrid storageGrid = null;
		
		for (StorageGrid sg : lockers.get(0).getStorageGrids())
			if (sg.getGridNum() == gridNo) {
				storageGrid = sg;
				break;
			}
		
		StorageGridPurchaserNews sgpn = new StorageGridPurchaserNews();
		sgpn.setStorageGrid(storageGrid);
		sgpn.setCardNumber(purchaser.getCardInfo().getCardNumber());
		sgpn.setDelivery(1);
		sgpn.setClosing(0);
		sgpn.setArrivalTime(deliveryTime);
		sgpn.setPick(0);
		sgpn.setRfidSn(storageRfid);
		sgpn.setPurchaser(purchaser);
		sgpn.setLockersId(lockers.get(0).getLockersId());
		sgpn.setLocationId(lockers.get(0).getLocation().getLocationId());
		sgpn.setOrderInformationNumber(orderInformation.getNumber());
		sgpn.setGroupId(group.getGroupId());
		sgpn.setDeviceSn(deviceSn);
		sgpn.setRefund(0);
		
		entityManager.persist(sgpn);
		
		entityManager.flush();

		String email = purchaser.getEmail();
		
		Map<String, Object> informMap = informMessage.queryInformMessage(purchaser.getLanguage(), 2, 3);
		
		Object[] objs = {lockers.get(0).getLocation().getVilliage().getName() + lockers.get(0).getLocation().getName() + lockers.get(0).getLockersName(), passwd, group.getHotline()};
		
		if (null != phone && !"".equals(phone) && informMap.containsKey(InformMessageLocal.SMS_INFORM)){
			String message = ((SmsInfo)informMap.get(InformMessageLocal.SMS_INFORM)).getSmsContent();
			
			message = MessageFormat.format(message, objs);
			
			logger.info("SMS message -> " + message);
			
			//new SMSScheduler(phone, message, objs, "123", group.getSmsChannel(), group.getName(), true).start();
			
			String papams="{\"address\":\""+objs[0]+"\",\"passwd\":\""+objs[1]+"\"}";
			new AlidayuSMS(phone,"SMS_5450197","到货通知",papams,message,new SaveSmsInfo()).start();
			
		} else if (null != email && !"".equals(email) && informMap.containsKey(InformMessageLocal.EMAIL_INFORM)){
			EmailInfo emailInfo = (EmailInfo) informMap.get(InformMessageLocal.EMAIL_INFORM);
			
			String message = emailInfo.getContent();
			
			message = MessageFormat.format(message, objs);
			
			logger.info("E-MAIL message -> " + message);
			
			new EMAILScheduler(email, emailInfo.getTitle(), message).start();
			
		}
		
		result.accumulate("userId", purchaser.getCardInfo().getCardNumber());
		result.accumulate("passwd", passwd);
		
		return result.toString();
	}
	
	@SuppressWarnings("unchecked")
	private String getPasswd(String passwd){
		List<ProductBatch> list = entityManager.createQuery("select pb from ProductBatch pb where pb.passwd = '" + passwd + "' and (pb.orderInformation.transactions = 3 or pb.orderInformation.transactions = 6)").getResultList();
		
		if (list.size() > 0) {
			passwd = CommEntryUtil.randomPasswd();
			return getPasswd(passwd);
		}
		
		return passwd;
	}
}
